package com.rizzo.infrastructure.redis.config;

import com.rizzo.infrastructure.domain.KeyType;
import com.rizzo.infrastructure.redis.key.RedisKey;
import com.rizzo.infrastructure.redis.key.RedisKeyBuilder;
import com.rizzo.infrastructure.redis.timeseries.TimeStep;
import org.joda.time.Period;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import java.util.Map;

public class RedisConfigManager {

	private RedisTemplate<RedisKey, String> redisKeyTemplate;

	private RedisKey systemRedisKey;

	public RedisConfigManager(RedisTemplate<RedisKey, String> redisKeyTemplate, String systemApplicationKey,
			Map<String, Object> defaultSystemConfigMap) {
		this.redisKeyTemplate = redisKeyTemplate;
		this.systemRedisKey = new RedisKeyBuilder().key(systemApplicationKey).type(KeyType.CONFIG).data(RedisKey.ANONYMOUS).build();
		// on startup persist the default system config map
		createSystemConfig(defaultSystemConfigMap);
	}

	public String getUserConfig(String user, String application, String configKey) {
		RedisKey userRedisKey = new RedisKeyBuilder().key(application).type(KeyType.CONFIG).data(user).build();
		HashOperations<RedisKey, String, String> hashOperations = this.redisKeyTemplate.opsForHash();
		final String userValue = hashOperations.get(userRedisKey, configKey);
		if (StringUtils.hasText(userValue)) {
			return userValue;
		} else {
			// fallback to the default system setting
			return getSystemConfig(configKey);
		}
	}

	public String getSystemConfig(String configKey) {
		HashOperations<RedisKey, String, String> hashOperations = this.redisKeyTemplate.opsForHash();
		return hashOperations.get(systemRedisKey, configKey);
	}

	private void createSystemConfig(Map<String, Object> defaultSystemConfigMap) {
		if (defaultSystemConfigMap != null) {
			for (Map.Entry<String, Object> keyValueEntry : defaultSystemConfigMap.entrySet()) {
				HashOperations<RedisKey, String, String> hashOperations = this.redisKeyTemplate.opsForHash();
				String presentValue = hashOperations.get(systemRedisKey, keyValueEntry.getKey());
				if (!StringUtils.hasText(presentValue)) {
					// insert it
					if (keyValueEntry.getValue() instanceof Period) {
						hashOperations.put(systemRedisKey, keyValueEntry.getKey(), TimeStep.getStandardISOPeriod((Period) keyValueEntry.getValue()));
					} else {
						hashOperations.put(systemRedisKey, keyValueEntry.getKey(), keyValueEntry.getValue().toString());
					}
				}
			}
		}
	}

}
